package com.jiayu.wheel.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;


/**
 * 切面类
 * @author Administrator
 */
@Aspect
@Component
public class AopLog {

//   无异常时通知顺序：
//    1.前环绕
//    2.前通知
//    3.返回结果后通知
//    4.后通知
//    5.后环绕
//    有异常时通知顺序（无【返回结果后通知】和【后环绕】）：
//    1.前通知
//    2.前置通知
//    3.异常通知
//    4.后置通知

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 线程局部变量，用于解决多线程中相同变量访问冲突问题！
     */
    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 切入点表达式的标准格式：动作关键字（访问修饰符，返回值，包名，.类/接口名.方法名（参数）异常名）
     */
    @Pointcut(value = "execution(public * com.jiayu.wheel.aop..*.*(..))")
    public void aopWebLog(){

    }

    @Around("aopWebLog()")
    public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        logger.info("【环绕通知前】");
        proceedingJoinPoint.proceed();
        logger.info("【环绕通知后】");
    }

    @Before("aopWebLog()")
    public void doBefore(JoinPoint joinPoint){
        logger.info("【前置通知】");
        startTime.set(System.currentTimeMillis());
        logger.info("类的方法" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
    }

    @AfterReturning(pointcut = "aopWebLog()",returning = "object")
    public void doAfterReturning(Object object){
        logger.info("【返回结果后通知】");
        logger.info("应答值:"+object);
        logger.info("耗时:"+(System.currentTimeMillis()-startTime.get()));
        startTime.remove();
    }

    @After("aopWebLog()")
    public void doAfter(){
        logger.info("【后置通知】");
    }

    @AfterThrowing(pointcut = "aopWebLog()",throwing = "ex")
    public void addAfterThrowingLogger(JoinPoint joinPoint,Exception ex){
        logger.info("【异常通知】");
        logger.error("执行异常:"+ ex.getMessage());
    }






}
